package org.luxor.commons.redis.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.luxor.commons.core.exception.BaseException;
import org.luxor.commons.core.utils.StringUtils;
import org.luxor.commons.core.web.RestStatus;
import org.luxor.commons.redis.annotation.Idempotent;
import org.luxor.commons.redis.client.RedisStringClient;
import org.luxor.commons.redis.component.KeyGenerator;
import org.luxor.commons.redis.component.RedisKeys;
import org.luxor.commons.redis.component.ReflectUtil;

/**
 * 限制接口幂等调用的AOP实现类
 *
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017-07-17 23:30
 */
@Aspect
public class IdempotentAspect {

    private RedisStringClient redisStringClient;

    public void setRedisClientString(RedisStringClient redisStringClient) {
        this.redisStringClient = redisStringClient;
    }

    /**
     * 定义缓存逻辑
     */
    @Around("@annotation(org.luxor.commons.redis.annotation.Idempotent)")
    public Object idempotent(ProceedingJoinPoint pjp) throws Throwable {
        Idempotent idempotent = ReflectUtil.getMethod(pjp).getAnnotation(Idempotent.class);
        String tokenVal = KeyGenerator.INSTANCE.getIdempotentToken(pjp, idempotent);

        String limitRateKey = RedisKeys.builder("idempotent").append(tokenVal).build();
        String tokenResult = redisStringClient.get(limitRateKey);
        if (StringUtils.equals(tokenVal,tokenResult)) {
            redisStringClient.delete(limitRateKey);
            return pjp.proceed();
        }
        throw new BaseException(RestStatus.IDEMPOTENT_ERROR);
    }

}